Pressidian
花园入口
笔记
项目
关于
实验室
GitHub
花园入口
笔记
项目
关于
实验室
GitHub

KNOWLEDGE PATHS

笔记库
当前位置
笔记库/前端/面试/八股/JS

深拷贝使用json化的问题 ⌚️

2 分钟阅读 · Note

目录树 578 篇

            • 代码运行过程
            • 深拷贝使用json化的问题 ⌚️
            • 暂时性死区 ⌚️
            • Call、Apply与Bind的区别 ⌚️
            • Iterable&Enumerable
            • JS
            • label
            • Realm
            • var、let、const的区别 ⌚️
          • 进阶篇题目列表
          • DOM&浏览器 API
          • HTTP&网络
          • TS
          • Vue
        • 可投递企业
      • 前端技术栈
    • 笔记目录
    • CLAUDE.md
    • Vue 组件与 Render 函数

关联笔记 6

↗代码运行过程同一路径↗暂时性死区 ⌚️同一路径↗Call、Apply与Bind的区别 ⌚️同一路径↗Iterable&Enumerable同一路径↗JS同一路径↗label同一路径

在 JavaScript 中,使用 JSON.parse(JSON.stringify(obj)) 来实现深拷贝虽然看似简洁,但它仅适用于纯 JSON 兼容的简单数据结构。在实际开发中,这种方式存在多个严重的局限性,需要特别注意以下问题:

无法处理特定数据类型

JSON 格式本身不支持 JavaScript 中的部分特有类型,在序列化时会出现丢失或转换错误:

  • 函数与 undefined:对象中包含的函数属性会被直接忽略,而值为 undefined 的属性也会被删除。
  • Symbol 与 BigInt:遇到这两种类型时,JSON.stringify() 会直接抛出错误。
  • Date 对象:日期对象会被转换为 ISO 格式的字符串,导致克隆后的对象失去 Date 实例的功能(如 instanceof Date 为 false)。
  • RegExp 正则对象:正则表达式会被转换为空对象 {}。

复杂数据结构的降级

对于现代 JavaScript 中常用的内置数据结构,JSON 序列化无法正确还原:

  • Map 和 Set:这些集合类型会被转换为普通的空对象 {},其内部键值对完全丢失。
  • Typed Arrays 与 ArrayBuffer:带类型的数组和缓冲区无法被正确处理。
  • 原型链与构造器信息丢失:该方法只能生成普通对象(plain object),所有自定义的原型、类实例以及继承关系都会被丢弃。

无法处理循环引用

当对象内部存在循环引用(例如 a.b = a)时,JSON.stringify() 会直接抛出 TypeError: Converting circular structure to JSON 错误,导致深拷贝失败。它本身不具备检测或替换循环引用的能力。

其他隐性问题

  • 精度丢失:超大数字(大于 $2^{53} - 1$)在 JSON 中可能会被截断或转为科学计数法,解析后数值不再准确。
  • 不可枚举属性丢失:通过 Object.defineProperty 设置的不可枚举属性会被跳过。
  • 特殊值过滤:NaN 和 Infinity 会被转换为 null;键名为 null 或 undefined 的属性可能会变成字符串 "null" 或被忽略。

最佳实践建议

真正需要可靠的深拷贝时,建议优先使用现代浏览器及 Node.js 17+ 原生支持的 structuredClone() 方法。它能够完美处理循环引用、Date、Map、Set 等复杂类型。只有在明确知道数据仅为简单的嵌套对象/数组,且不包含上述任何特殊值时,才可以谨慎使用 JSON 方案。